export interface EliminateValidaterOption<T = any> {
  array: T[]
  target?: undefined
  validater: (item: T, index: number) => boolean
}

export interface EliminateValueOption<T = any> {
  array: T[]
  target: T
  validater?: undefined
}

export type EliminateOption<T = any> = EliminateValidaterOption<T> | EliminateValueOption<T>

/**
 * 剔除数组中的项
 * @param array 数组
 * @param target 需要剔除的数据
 */
export function eliminate<T>(option: EliminateOption<T>) {
  const { array, target, validater } = option

  const fn = typeof validater === 'function' ? validater : (value: T) => target === value

  for (let index = array.length; index--; ) {
    if (fn(array[index], index)) {
      array.splice(index, 1)
    }
  }
  return array
}

export enum FileReaderType {
  TEXT,
  BASE64,
  BUFFER
}

/**
 * @param file 二进制对象（File类型 或 Blob类型）
 * @param type 以怎样的方式读取
 * @param encoding 传入一个字符串类型的编码类型，如缺省，则默认为“utf-8”类型
 */
export function fileReader(file: File | Blob, type: FileReaderType.TEXT | FileReaderType.BASE64, encoding?: string): Promise<string>
export function fileReader(file: File | Blob, type: FileReaderType.BUFFER, encoding?: string): Promise<ArrayBuffer>
export function fileReader(file: File | Blob, type: FileReaderType, encoding?: string) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    // 返回错误信息
    reader.addEventListener('error', function () {
      reject(new Error('FileReader 读取资源失败'))
    })
    // 读取成功，返回读取到的资源
    reader.addEventListener('load', function () {
      resolve(reader.result)
    })
    // 不同的读取方式
    switch (type) {
      case FileReaderType.TEXT:
        reader.readAsText(file, encoding || 'utf-8')
        break
      case FileReaderType.BASE64:
        reader.readAsDataURL(file)
        break
      default:
        reader.readAsArrayBuffer(file)
        break
    }
  })
}

export function logError(error: any) {
  if (import.meta.env.DEV) {
    console.error(error)
  }
}

export function merge(source: any, target: any) {
  if (isObject<Record<string, any>>(source) && isObject<Record<string, any>>(target)) {
    for (const key in target) {
      if (source[key]) {
        source[key] = merge(source[key], target[key])
      } else {
        source[key] = target[key]
      }
    }
    return source
  }

  if (Array.isArray(source) && Array.isArray(target)) {
    source.push(...target.filter((value) => !source.includes(value)))
    return source
  }

  return target
}

const _toString = Object.prototype.toString

export function isObject<T extends object>(target: any): target is T {
  return _toString.call(target) === '[object Object]'
}
